package com.hank.websocketdemo.handler;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.hank.websocketdemo.DTO.SessionDTO;
import com.hank.websocketdemo.domain.ChatGroup;
import com.hank.websocketdemo.domain.ChatOnlineUser;
import com.hank.websocketdemo.service.ChatGroupService;
import com.hank.websocketdemo.service.ChatMessageService;
import com.hank.websocketdemo.service.ChatOnlineUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;

import java.io.IOException;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author gaoZhiHao
 * @date 2023/5/18 14:25
 */
@Component
public class ChatMessageHandler extends TextWebSocketHandler {

//    @Autowired
//    private ChatGroupService chatGroupService;
//
//    @Autowired
//    private ChatMessageService chatMessageService;
//
//    @Autowired
//    private ChatOnlineUserService chatOnlineUserService;

    private static final Map<String, Set<SessionDTO>> sessionsGroup = new ConcurrentHashMap<>();

    private static final Map<String, WebSocketSession> sessions = new ConcurrentHashMap<>();

    private final Map<String, String> userNames = new ConcurrentHashMap<>();

    public static final String GROUP_ID1 = "1";

    public static final String GROUP_ID2 = "2";

    static {
        sessionsGroup.put(GROUP_ID1, new HashSet<>());
        sessionsGroup.put(GROUP_ID2, new HashSet<>());
    }

    @Override
    public void afterConnectionEstablished(WebSocketSession session) {
        String sessionId = session.getId();
        sessions.put(sessionId, session);
    }

    @Override
    protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
        String payload = message.getPayload();
        JsonObject jsonObject = JsonParser.parseString(payload).getAsJsonObject();
        String type = jsonObject.get("type").getAsString();
        String groupId = jsonObject.get("groupId").getAsString();
        if ("join".equals(type)) {
            String userName = jsonObject.get("userName").getAsString();
            userNames.put(session.getId(), userName);
            SessionDTO sessionDTO = new SessionDTO();
            sessionDTO.setSessionId(session.getId());
            sessionDTO.setSession(session);
            sessionsGroup.get(groupId).add(sessionDTO);
            JsonObject joinMessage = new JsonObject();
            joinMessage.addProperty("type", "join");
            joinMessage.addProperty("userName", userName);
            joinMessage.addProperty("groupId", groupId);
            broadcast(joinMessage.toString(), groupId);
        } else if ("chat".equals(type)) {
            String userName = userNames.get(session.getId());
            String text = jsonObject.get("text").getAsString();

            JsonObject chatMessage = new JsonObject();
            chatMessage.addProperty("type", "chat");
            chatMessage.addProperty("userName", userName);
            chatMessage.addProperty("text", text);
            chatMessage.addProperty("groupId", groupId);
            broadcast(chatMessage.toString(), groupId);
        }

    }

    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
        sessions.remove(session.getId());
        String userName = userNames.get(session.getId());
        SessionDTO sessionDTO = new SessionDTO();
        sessionDTO.setSessionId(session.getId());
        sessionDTO.setSession(session);
        for (Map.Entry<String, Set<SessionDTO>> stringSetEntry : sessionsGroup.entrySet()) {
            for (SessionDTO dto : stringSetEntry.getValue()) {
                if(dto.equals(sessionDTO)){
                    stringSetEntry.getValue().remove(sessionDTO);
                    JsonObject leaveMessage = new JsonObject();
                    leaveMessage.addProperty("type", "leave");
                    leaveMessage.addProperty("userName", userName);
                    leaveMessage.addProperty("groupId", stringSetEntry.getKey());
                    broadcast(leaveMessage.toString(),stringSetEntry.getKey());
                }
            }
        }
    }

    private void broadcast(String message, String groupId) {
        sessionsGroup.get(groupId).forEach(sessionDTO ->
                {
                    try {
                        sessionDTO.getSession().sendMessage(new TextMessage(message));
                    } catch (IOException e) {
                        throw new RuntimeException(e);
                    }
                }
        );
    }
}
